static void *njs_regexp_malloc(size_t size, void *memory_data);
static void njs_regexp_free(void *p, void *memory_data);
-static njs_int_t njs_regexp_prototype_source(njs_vm_t *vm,
- njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
- njs_value_t *retval);
+static njs_int_t njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused);
static int njs_regexp_pattern_compile(njs_vm_t *vm, njs_regex_t *regex,
u_char *source, int options);
static u_char *njs_regexp_compile_trace_handler(njs_trace_t *trace,
pattern = njs_arg(args, nargs, 1);
if (njs_is_regexp(pattern)) {
- ret = njs_regexp_prototype_source(vm, NULL, pattern, NULL, &source);
+ ret = njs_regexp_prototype_source(vm, pattern, 1, 0);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
+ source = vm->retval;
+
re_flags = njs_regexp_value_flags(vm, pattern);
pattern = &source;
static njs_int_t
-njs_regexp_prototype_global(njs_vm_t *vm, njs_object_prop_t *prop,
- njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+njs_regexp_prototype_flags(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
{
- njs_regexp_pattern_t *pattern;
+ u_char *p;
+ njs_int_t ret;
+ njs_value_t *this, value;
+ u_char dst[3];
- pattern = njs_regexp_pattern(value);
- *retval = pattern->global ? njs_value_true : njs_value_false;
- njs_release(vm, value);
+ static const njs_value_t string_global = njs_string("global");
+ static const njs_value_t string_ignore_case = njs_string("ignoreCase");
+ static const njs_value_t string_multiline = njs_string("multiline");
- return NJS_OK;
-}
+ this = njs_argument(args, 0);
+ if (njs_slow_path(!njs_is_object(this))) {
+ njs_type_error(vm, "\"this\" argument is not an object");
+ return NJS_ERROR;
+ }
+ p = &dst[0];
-static njs_int_t
-njs_regexp_prototype_ignore_case(njs_vm_t *vm, njs_object_prop_t *prop,
- njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
-{
- njs_regexp_pattern_t *pattern;
+ ret = njs_value_property(vm, this, njs_value_arg(&string_global),
+ &value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
- pattern = njs_regexp_pattern(value);
- *retval = pattern->ignore_case ? njs_value_true : njs_value_false;
- njs_release(vm, value);
+ if (njs_bool(&value)) {
+ *p++ = 'g';
+ }
- return NJS_OK;
+ ret = njs_value_property(vm, this, njs_value_arg(&string_ignore_case),
+ &value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ if (njs_bool(&value)) {
+ *p++ = 'i';
+ }
+
+ ret = njs_value_property(vm, this, njs_value_arg(&string_multiline),
+ &value);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ if (njs_bool(&value)) {
+ *p++ = 'm';
+ }
+
+ return njs_string_new(vm, &vm->retval, dst, p - dst, p - dst);
}
static njs_int_t
-njs_regexp_prototype_multiline(njs_vm_t *vm, njs_object_prop_t *prop,
- njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+njs_regexp_prototype_flag(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t flag)
{
+ unsigned yn;
+ njs_value_t *this;
njs_regexp_pattern_t *pattern;
- pattern = njs_regexp_pattern(value);
- *retval = pattern->multiline ? njs_value_true : njs_value_false;
- njs_release(vm, value);
+ this = njs_argument(args, 0);
+ if (njs_slow_path(!njs_is_object(this))) {
+ njs_type_error(vm, "\"this\" argument is not an object");
+ return NJS_ERROR;
+ }
+
+ if (njs_slow_path(!njs_is_regexp(this))) {
+ if (njs_object(this) == &vm->prototypes[NJS_OBJ_TYPE_REGEXP].object) {
+ njs_set_undefined(&vm->retval);
+ return NJS_OK;
+ }
+
+ njs_type_error(vm, "\"this\" argument is not a regexp");
+ return NJS_ERROR;
+ }
+
+ pattern = njs_regexp_pattern(this);
+
+ switch (flag) {
+ case NJS_REGEXP_GLOBAL:
+ yn = pattern->global;
+ break;
+
+ case NJS_REGEXP_IGNORE_CASE:
+ yn = pattern->ignore_case;
+ break;
+
+ case NJS_REGEXP_MULTILINE:
+ default:
+ yn = pattern->multiline;
+ break;
+ }
+
+ njs_set_boolean(&vm->retval, yn);
return NJS_OK;
}
static njs_int_t
-njs_regexp_prototype_source(njs_vm_t *vm, njs_object_prop_t *prop,
- njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
{
u_char *source;
int32_t length;
uint32_t size;
+ njs_value_t *this;
njs_regexp_pattern_t *pattern;
- pattern = njs_regexp_pattern(value);
+ this = njs_argument(args, 0);
+ if (njs_slow_path(!njs_is_object(this))) {
+ njs_type_error(vm, "\"this\" argument is not an object");
+ return NJS_ERROR;
+ }
+
+ if (njs_slow_path(!njs_is_regexp(this))) {
+ if (njs_object(this) == &vm->prototypes[NJS_OBJ_TYPE_REGEXP].object) {
+ vm->retval = njs_string_empty_regexp;
+ return NJS_OK;
+ }
+
+ njs_type_error(vm, "\"this\" argument is not a regexp");
+ return NJS_ERROR;
+ }
+
+ pattern = njs_regexp_pattern(this);
/* Skip starting "/". */
source = pattern->source + 1;
size = njs_strlen(source) - pattern->flags;
length = njs_utf8_length(source, size);
- return njs_regexp_string_create(vm, retval, source, size, length);
+ return njs_regexp_string_create(vm, &vm->retval, source, size, length);
}
njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
- if (njs_is_regexp(njs_arg(args, nargs, 0))) {
- return njs_regexp_to_string(vm, &vm->retval, &args[0]);
+ u_char *p;
+ size_t size, length;
+ njs_int_t ret;
+ njs_value_t *r, source, flags;
+ njs_string_prop_t source_string, flags_string;
+
+ static const njs_value_t string_source = njs_string("source");
+ static const njs_value_t string_flags = njs_string("flags");
+
+ r = njs_argument(args, 0);
+
+ if (njs_slow_path(!njs_is_object(r))) {
+ njs_type_error(vm, "\"this\" argument is not an object");
+ return NJS_ERROR;
}
- njs_type_error(vm, "\"this\" argument is not a regexp");
+ ret = njs_value_property(vm, r, njs_value_arg(&string_source),
+ &source);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
- return NJS_ERROR;
+ ret = njs_value_to_string(vm, &source, &source);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_property(vm, r, njs_value_arg(&string_flags),
+ &flags);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_to_string(vm, &flags, &flags);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ (void) njs_string_prop(&source_string, &source);
+ (void) njs_string_prop(&flags_string, &flags);
+
+ size = source_string.size + flags_string.size + njs_length("//");
+ length = source_string.length + flags_string.length + njs_length("//");
+
+ if (njs_is_byte_string(&source_string)
+ || njs_is_byte_string(&flags_string))
+ {
+ length = 0;
+ }
+
+ p = njs_string_alloc(vm, &vm->retval, size, length);
+ if (njs_slow_path(p == NULL)) {
+ return NJS_ERROR;
+ }
+
+ *p++ = '/';
+ p = njs_cpymem(p, source_string.start, source_string.size);
+ *p++ = '/';
+ memcpy(p, flags_string.start, flags_string.size);
+
+ return NJS_OK;
}
njs_regexp_to_string(njs_vm_t *vm, njs_value_t *retval,
const njs_value_t *value)
{
- u_char *source;
+ u_char *p, *source;
int32_t length;
uint32_t size;
njs_regexp_pattern_t *pattern;
size = njs_strlen(source);
length = njs_utf8_length(source, size);
- return njs_regexp_string_create(vm, retval, source, size, length);
+ length = (length >= 0) ? length: 0;
+
+ p = njs_string_alloc(vm, retval, size, length);
+ if (njs_slow_path(p == NULL)) {
+ return NJS_ERROR;
+ }
+
+ p = njs_cpymem(p, source, size);
+
+ return NJS_OK;
}
},
{
- .type = NJS_PROPERTY_HANDLER,
+ .type = NJS_PROPERTY,
+ .name = njs_string("flags"),
+ .value = njs_value(NJS_INVALID, 1, NAN),
+ .getter = njs_native_function(njs_regexp_prototype_flags, 0),
+ .setter = njs_value(NJS_UNDEFINED, 0, NAN),
+ .writable = NJS_ATTRIBUTE_UNSET,
+ .configurable = 1,
+ .enumerable = 0,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("global"),
- .value = njs_prop_handler(njs_regexp_prototype_global),
+ .value = njs_value(NJS_INVALID, 1, NAN),
+ .getter = njs_native_function2(njs_regexp_prototype_flag, 0,
+ NJS_REGEXP_GLOBAL),
+ .setter = njs_value(NJS_UNDEFINED, 0, NAN),
+ .writable = NJS_ATTRIBUTE_UNSET,
.configurable = 1,
+ .enumerable = 0,
},
{
- .type = NJS_PROPERTY_HANDLER,
+ .type = NJS_PROPERTY,
.name = njs_string("ignoreCase"),
- .value = njs_prop_handler(njs_regexp_prototype_ignore_case),
+ .value = njs_value(NJS_INVALID, 1, NAN),
+ .getter = njs_native_function2(njs_regexp_prototype_flag, 0,
+ NJS_REGEXP_IGNORE_CASE),
+ .setter = njs_value(NJS_UNDEFINED, 0, NAN),
+ .writable = NJS_ATTRIBUTE_UNSET,
.configurable = 1,
+ .enumerable = 0,
},
{
- .type = NJS_PROPERTY_HANDLER,
+ .type = NJS_PROPERTY,
.name = njs_string("multiline"),
- .value = njs_prop_handler(njs_regexp_prototype_multiline),
+ .value = njs_value(NJS_INVALID, 1, NAN),
+ .getter = njs_native_function2(njs_regexp_prototype_flag, 0,
+ NJS_REGEXP_MULTILINE),
+ .setter = njs_value(NJS_UNDEFINED, 0, NAN),
+ .writable = NJS_ATTRIBUTE_UNSET,
.configurable = 1,
+ .enumerable = 0,
},
{
- .type = NJS_PROPERTY_HANDLER,
+ .type = NJS_PROPERTY,
.name = njs_string("source"),
- .value = njs_prop_handler(njs_regexp_prototype_source),
+ .value = njs_value(NJS_INVALID, 1, NAN),
+ .getter = njs_native_function(njs_regexp_prototype_source, 0),
+ .setter = njs_value(NJS_UNDEFINED, 0, NAN),
+ .writable = NJS_ATTRIBUTE_UNSET,
.configurable = 1,
+ .enumerable = 0,
},
{
.constructor = njs_native_ctor(njs_regexp_constructor, 2, 0),
.constructor_props = &njs_regexp_constructor_init,
.prototype_props = &njs_regexp_prototype_init,
- .prototype_value = { .object = { .type = NJS_REGEXP } },
+ .prototype_value = { .object = { .type = NJS_OBJECT } },
};