module extension: add support for canonical name resolution (#2013)
Before attempting to load a module, each provided resolver must be given an opportunity to examine the name of the requested module without actually loading it so as to canonicalize it, in case a module can be referred to by multiple names. Then, modules are loaded and cached by their canonical name. JerryScript-DCO-1.0-Signed-off-by: Gabriel Schulhof gabriel.schulhof@intel.com
This commit is contained in:
committed by
Zoltan Herczeg
parent
e527e41bac
commit
6d53931055
@@ -60,11 +60,18 @@ const char eval_string5[] =
|
||||
" return x === y ? 1 : 0;"
|
||||
"}) ();";
|
||||
|
||||
/*
|
||||
* Define a resolver for a module named "differently-handled-module" to check that custom resolvers work.
|
||||
*/
|
||||
static bool
|
||||
resolve_differently_handled_module (const jerry_char_t *name,
|
||||
jerry_value_t *result)
|
||||
resolve_differently_handled_module (const jerry_value_t name,
|
||||
jerry_value_t *result)
|
||||
{
|
||||
if (!strcmp ((char *) name, "differently-handled-module"))
|
||||
jerry_size_t name_size = jerry_get_utf8_string_size (name);
|
||||
jerry_char_t name_string[name_size];
|
||||
jerry_string_to_utf8_char_buffer (name, name_string, name_size);
|
||||
|
||||
if (!strncmp ((char *) name_string, "differently-handled-module", name_size))
|
||||
{
|
||||
(*result) = jerry_create_number (29);
|
||||
return true;
|
||||
@@ -72,16 +79,26 @@ resolve_differently_handled_module (const jerry_char_t *name,
|
||||
return false;
|
||||
} /* resolve_differently_handled_module */
|
||||
|
||||
static jerryx_module_resolver_t differently_handled_module_resolver =
|
||||
{
|
||||
NULL,
|
||||
resolve_differently_handled_module
|
||||
};
|
||||
|
||||
/*
|
||||
* Define module "cache-check" via its own resolver as an empty object. Since objects are accessible only via references
|
||||
* we can strictly compare the object returned on subsequent attempts at loading "cache-check" with the object returned
|
||||
* on the first attempt and establish that the two are in fact the same object - which in turn shows that caching works.
|
||||
*/
|
||||
static bool
|
||||
cache_check (const jerry_char_t *name,
|
||||
cache_check (const jerry_value_t name,
|
||||
jerry_value_t *result)
|
||||
{
|
||||
if (!strcmp ((char *) name, "cache-check"))
|
||||
jerry_size_t name_size = jerry_get_utf8_string_size (name);
|
||||
jerry_char_t name_string[name_size];
|
||||
jerry_string_to_utf8_char_buffer (name, name_string, name_size);
|
||||
|
||||
if (!strncmp ((char *) name_string, "cache-check", name_size))
|
||||
{
|
||||
(*result) = jerry_create_object ();
|
||||
return true;
|
||||
@@ -89,13 +106,19 @@ cache_check (const jerry_char_t *name,
|
||||
return false;
|
||||
} /* cache_check */
|
||||
|
||||
static const jerryx_module_resolver_t resolvers[3] =
|
||||
static jerryx_module_resolver_t cache_check_resolver =
|
||||
{
|
||||
jerryx_module_native_resolver,
|
||||
resolve_differently_handled_module,
|
||||
NULL,
|
||||
cache_check
|
||||
};
|
||||
|
||||
static const jerryx_module_resolver_t *resolvers[3] =
|
||||
{
|
||||
&jerryx_module_native_resolver,
|
||||
&differently_handled_module_resolver,
|
||||
&cache_check_resolver
|
||||
};
|
||||
|
||||
static jerry_value_t
|
||||
handle_require (const jerry_value_t js_function,
|
||||
const jerry_value_t this_val,
|
||||
@@ -107,16 +130,9 @@ handle_require (const jerry_value_t js_function,
|
||||
(void) args_count;
|
||||
|
||||
jerry_value_t return_value = 0;
|
||||
jerry_char_t module_name[256] = "";
|
||||
jerry_size_t bytes_copied = 0;
|
||||
|
||||
TEST_ASSERT (args_count == 1);
|
||||
bytes_copied = jerry_string_to_char_buffer (args_p[0], module_name, 256);
|
||||
if (bytes_copied < 256)
|
||||
{
|
||||
module_name[bytes_copied] = 0;
|
||||
return_value = jerryx_module_resolve (module_name, resolvers, 3);
|
||||
}
|
||||
return_value = jerryx_module_resolve (args_p[0], resolvers, 3);
|
||||
|
||||
return return_value;
|
||||
} /* handle_require */
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "jerryscript.h"
|
||||
#include "test-common.h"
|
||||
#include "jerryscript-ext/module.h"
|
||||
|
||||
#define ACTUAL_NAME "alice"
|
||||
#define ALIAS_NAME "bob"
|
||||
|
||||
static jerry_value_t
|
||||
get_canonical_name (const jerry_value_t name)
|
||||
{
|
||||
jerry_size_t name_size = jerry_get_string_size (name);
|
||||
jerry_char_t name_string[name_size + 1];
|
||||
jerry_string_to_char_buffer (name, name_string, name_size);
|
||||
name_string[name_size] = 0;
|
||||
|
||||
if (!strcmp ((char *) name_string, ACTUAL_NAME))
|
||||
{
|
||||
return jerry_acquire_value (name);
|
||||
}
|
||||
else if (!strcmp ((char *) name_string, ALIAS_NAME))
|
||||
{
|
||||
return jerry_create_string ((jerry_char_t *) ACTUAL_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
return jerry_create_undefined ();
|
||||
}
|
||||
} /* get_canonical_name */
|
||||
|
||||
static bool
|
||||
resolve (const jerry_value_t canonical_name, jerry_value_t *result)
|
||||
{
|
||||
jerry_size_t name_size = jerry_get_string_size (canonical_name);
|
||||
jerry_char_t name_string[name_size + 1];
|
||||
jerry_string_to_char_buffer (canonical_name, name_string, name_size);
|
||||
name_string[name_size] = 0;
|
||||
|
||||
if (!strcmp ((char *) name_string, ACTUAL_NAME))
|
||||
{
|
||||
*result = jerry_create_object ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* resolve */
|
||||
|
||||
static const jerryx_module_resolver_t canonical_test =
|
||||
{
|
||||
.get_canonical_name_p = get_canonical_name,
|
||||
.resolve_p = resolve
|
||||
};
|
||||
|
||||
#define TEST_VALUE 95.0
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
const jerryx_module_resolver_t *resolver = &canonical_test;
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t actual_name = jerry_create_string ((jerry_char_t *) ACTUAL_NAME);
|
||||
jerry_value_t alias_name = jerry_create_string ((jerry_char_t *) ALIAS_NAME);
|
||||
|
||||
/* It's important that we resolve by the non-canonical name first. */
|
||||
jerry_value_t result2 = jerryx_module_resolve (alias_name, &resolver, 1);
|
||||
jerry_value_t result1 = jerryx_module_resolve (actual_name, &resolver, 1);
|
||||
jerry_release_value (actual_name);
|
||||
jerry_release_value (alias_name);
|
||||
|
||||
/* An elaborate way of doing strict equal - set a property on one object and it "magically" appears on the other. */
|
||||
jerry_value_t prop_name = jerry_create_string ((jerry_char_t *) "something");
|
||||
jerry_value_t prop_value = jerry_create_number (TEST_VALUE);
|
||||
jerry_release_value (jerry_set_property (result1, prop_name, prop_value));
|
||||
jerry_release_value (prop_value);
|
||||
|
||||
prop_value = jerry_get_property (result2, prop_name);
|
||||
TEST_ASSERT (jerry_get_number_value (prop_value) == TEST_VALUE);
|
||||
jerry_release_value (prop_value);
|
||||
|
||||
jerry_release_value (prop_name);
|
||||
jerry_release_value (result1);
|
||||
jerry_release_value (result2);
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
@@ -26,12 +26,15 @@ main (int argc, char **argv)
|
||||
(void) argv;
|
||||
jerry_char_t buffer[256];
|
||||
jerry_size_t bytes_copied;
|
||||
jerryx_module_resolver_t resolver = jerryx_module_native_resolver;
|
||||
const jerryx_module_resolver_t *resolver = &jerryx_module_native_resolver;
|
||||
jerry_value_t module_name;
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
/* Attempt to load a non-existing module. */
|
||||
jerry_value_t module = jerryx_module_resolve ((jerry_char_t *) "some-unknown-module-name", &resolver, 1);
|
||||
module_name = jerry_create_string ((jerry_char_t *) "some-unknown-module-name");
|
||||
jerry_value_t module = jerryx_module_resolve (module_name, &resolver, 1);
|
||||
jerry_release_value (module_name);
|
||||
|
||||
TEST_ASSERT (jerry_value_has_error_flag (module));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user