0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 15:33:54 +01:00

ircd::js: Add recursive has(), get(), set(), del().

This commit is contained in:
Jason Volk 2016-10-23 22:44:41 -07:00
parent 9f85b39506
commit 6d7e1157b1
7 changed files with 280 additions and 24 deletions

32
include/ircd/js/del.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_JS_DEL_H
namespace ircd {
namespace js {
void del(const JS::HandleObject &obj, const id &id);
void del(const JS::HandleObject &src, const char *const path);
} // namespace js
} // namespace ircd

View file

@ -25,27 +25,8 @@
namespace ircd {
namespace js {
inline value
get(const object &obj,
const char *const name)
{
value ret;
if(!JS_GetProperty(*cx, obj, name, &ret))
throw reference_error("%s", name);
return ret;
}
inline value
get(const object &obj,
const id &id)
{
value ret;
if(!JS_GetPropertyById(*cx, obj, id, &ret))
throw reference_error("%s", string(id).c_str());
return ret;
}
value get(const JS::HandleObject &obj, const id &id);
value get(const JS::HandleObject &src, const char *const path);
} // namespace js
} // namespace ircd

32
include/ircd/js/has.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_JS_HAS_H
namespace ircd {
namespace js {
bool has(const JS::HandleObject &obj, const id &id);
bool has(const JS::HandleObject &src, const char *const path);
} // namespace js
} // namespace ircd

View file

@ -70,7 +70,10 @@ inline JSVersion version(const char *const &v) { return JS_StringToVersion(v);
#include "function_literal.h"
#include "vector.h"
#include "priv.h"
#include "has.h"
#include "get.h"
#include "set.h"
#include "del.h"
#include "call.h"
#include "for_each.h"
#include "trap.h"

View file

@ -29,7 +29,7 @@ IRCD_EXCEPTION(error, priv_error)
template<class T = void>
T &
priv(const object &obj,
priv(const JS::HandleObject &obj,
const JSClass &jsc)
{
const auto ret(JS_GetInstancePrivate(*cx, obj, &jsc, nullptr));
@ -41,7 +41,7 @@ priv(const object &obj,
template<class T = void>
T &
priv(const object &obj)
priv(const JS::HandleObject &obj)
{
const auto jsc(JS_GetClass(obj));
if(unlikely(!jsc))

32
include/ircd/js/set.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#define HAVE_IRCD_JS_SET_H
namespace ircd {
namespace js {
void set(const JS::HandleObject &obj, const id &id, const value &val);
void set(const JS::HandleObject &src, const char *const path, const value &val);
} // namespace js
} // namespace ircd

View file

@ -574,7 +574,7 @@ bool
ircd::js::trap::on_del(const JSObject &obj,
const jsid &id)
{
return false;
return true;
}
JS::Value
@ -779,6 +779,182 @@ ircd::js::call(const object &obj,
return call(obj, name.c_str(), args);
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/del.h
//
void
ircd::js::del(const JS::HandleObject &src,
const char *const path)
{
value val;
object obj(src);
const char *fail(nullptr);
tokens(path, ".", [&path, &val, &obj, &fail]
(char *const &part)
{
if(fail)
throw type_error("cannot recurse through non-object '%s' in `%s'", fail, path);
if(!JS_GetProperty(*cx, obj, part, &val) || undefined(val))
throw reference_error("%s", part);
object tmp(obj.get());
if(!JS_ValueToObject(*cx, val, &obj) || !obj.get())
{
fail = part;
obj = std::move(tmp);
}
});
del(obj, id(val));
}
void
ircd::js::del(const JS::HandleObject &obj,
const id &id)
{
JS::ObjectOpResult res;
if(!JS_DeletePropertyById(*cx, obj, id, res))
throw jserror(jserror::pending);
if(!res.checkStrict(*cx, obj, id))
throw jserror(jserror::pending);
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/set.h
//
void
ircd::js::set(const JS::HandleObject &src,
const char *const path,
const value &val)
{
value tmp;
object obj(src);
char buffer[strlen(path) + 1];
const char *fail(nullptr), *key(nullptr);
tokens(path, ".", buffer, sizeof(buffer), [&path, &tmp, &obj, &fail, &key]
(const char *const &part)
{
if(fail)
throw type_error("cannot recurse through non-object '%s' in `%s'", fail, path);
if(key)
throw reference_error("%s", part);
key = part;
if(!JS_GetProperty(*cx, obj, part, &tmp) || undefined(tmp))
return;
if(!JS_ValueToObject(*cx, tmp, &obj) || !obj.get())
fail = part;
});
if(!key)
return;
if(!JS_SetProperty(*cx, obj, key, val))
throw jserror(jserror::pending);
}
void
ircd::js::set(const JS::HandleObject &obj,
const id &id,
const value &val)
{
if(!JS_SetPropertyById(*cx, obj, id, val))
throw jserror(jserror::pending);
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/get.h
//
ircd::js::value
ircd::js::get(const JS::HandleObject &src,
const char *const path)
{
value ret;
object obj(src);
const char *fail(nullptr);
tokens(path, ".", [&obj, &path, &ret, &fail]
(const char *const &part)
{
if(fail)
throw type_error("cannot recurse through non-object '%s' in `%s'", fail, path);
if(!JS_GetProperty(*cx, obj, part, &ret) || undefined(ret))
throw reference_error("%s", part);
if(!JS_ValueToObject(*cx, ret, &obj) || !obj.get())
fail = part;
});
return ret;
}
ircd::js::value
ircd::js::get(const JS::HandleObject &obj,
const id &id)
{
value ret;
if(!JS_GetPropertyById(*cx, obj, id, &ret) || undefined(ret))
throw reference_error("%s", string(id).c_str());
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/has.h
//
bool
ircd::js::has(const JS::HandleObject &src,
const char *const path)
{
bool ret(true);
object obj(src);
const char *fail(nullptr);
tokens(path, ".", [&obj, &path, &ret, &fail]
(const char *const &part)
{
if(fail)
throw type_error("cannot recurse through non-object '%s' in `%s'", fail, path);
if(!JS_HasProperty(*cx, obj, part, &ret))
throw jserror(jserror::pending);
if(!ret)
return;
value tmp;
if(!JS_GetProperty(*cx, obj, part, &tmp) || undefined(tmp))
throw internal_error("%s", part);
if(!JS_ValueToObject(*cx, tmp, &obj) || !obj.get())
fail = part;
});
return ret;
}
bool
ircd::js::has(const JS::HandleObject &obj,
const id &id)
{
bool ret;
if(!JS_HasPropertyById(*cx, obj, id, &ret))
throw jserror(jserror::pending);
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/string.h