jsuno: Throw css.script.provider.ScriptExceptionRaisedException on JS errors
Signed-off-by: Stephan Bergmann <stephan.bergmann@collabora.com> Change-Id: Ia5df077d78b1650e28bf73716a10fdbd024f6e8a Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2077 Tested-by: Jenkins CPCI <releng@collaboraoffice.com> Reviewed-by: Michael Stahl <michael.stahl@collabora.com> (cherry picked from commit a4feac2f06bf3d1a6ed55a94dd5e05d01fc0f7c4) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205118 Reviewed-by: Neil Roberts <nroberts@libreoffice.org> Tested-by: Jenkins
This commit is contained in:
committed by
Neil Roberts
parent
bedeae9485
commit
368792e83c
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace jsuno
|
||||
{
|
||||
// @throws css.script.provider.ScriptExceptionRaisedException
|
||||
LO_DLLPUBLIC_JSUNO void execute(OUString const& script);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
|
||||
#
|
||||
# This file is part of the LibreOffice project.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Copyright the Collabora Office contributors.
|
||||
|
||||
$(eval $(call gb_CppunitTest_CppunitTest,jsuno_execute))
|
||||
|
||||
$(eval $(call gb_CppunitTest_add_exception_objects,jsuno_execute, \
|
||||
jsuno/qa/unit/execute \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_libraries,jsuno_execute, \
|
||||
jsuno \
|
||||
sal \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_sdk_api,jsuno_execute))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_ure,jsuno_execute))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
||||
@@ -15,6 +15,7 @@ $(eval $(call gb_Module_add_targets,jsuno, \
|
||||
|
||||
$(eval $(call gb_Module_add_check_targets,jsuno, \
|
||||
$(if $(ENABLE_EMBINDTEST_UNO),CppunitTest_jsuno_testuno) \
|
||||
CppunitTest_jsuno_execute \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Copyright the Collabora Office contributors.
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/plugin/TestPlugIn.h>
|
||||
|
||||
#include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp>
|
||||
#include <jsuno/jsuno.hxx>
|
||||
#include <rtl/ustring.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
class Execute : public CppUnit::TestFixture
|
||||
{
|
||||
public:
|
||||
void testThrows()
|
||||
{
|
||||
try
|
||||
{
|
||||
jsuno::execute(u"throw new Error('boom')"_ustr);
|
||||
CPPUNIT_FAIL("expected ScriptExceptionRaisedException");
|
||||
}
|
||||
catch (css::script::provider::ScriptExceptionRaisedException const& e)
|
||||
{
|
||||
CPPUNIT_ASSERT(e.Message.startsWith("boom"));
|
||||
CPPUNIT_ASSERT_EQUAL(u"<input>"_ustr, e.scriptName);
|
||||
CPPUNIT_ASSERT_EQUAL(u"JavaScript"_ustr, e.language);
|
||||
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), e.lineNum);
|
||||
CPPUNIT_ASSERT_EQUAL(u"Error"_ustr, e.exceptionType);
|
||||
}
|
||||
try
|
||||
{
|
||||
jsuno::execute(u"throw new TypeError('bad type')"_ustr);
|
||||
CPPUNIT_FAIL("expected ScriptExceptionRaisedException");
|
||||
}
|
||||
catch (css::script::provider::ScriptExceptionRaisedException const& e)
|
||||
{
|
||||
CPPUNIT_ASSERT(e.Message.startsWith("bad type"));
|
||||
CPPUNIT_ASSERT_EQUAL(u"TypeError"_ustr, e.exceptionType);
|
||||
}
|
||||
try
|
||||
{
|
||||
jsuno::execute(u"@@@ not valid JS"_ustr);
|
||||
CPPUNIT_FAIL("expected ScriptExceptionRaisedException");
|
||||
}
|
||||
catch (css::script::provider::ScriptExceptionRaisedException const& e)
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(u"SyntaxError"_ustr, e.exceptionType);
|
||||
}
|
||||
try
|
||||
{
|
||||
jsuno::execute(u"throw 'plain string'"_ustr);
|
||||
CPPUNIT_FAIL("expected ScriptExceptionRaisedException");
|
||||
}
|
||||
catch (css::script::provider::ScriptExceptionRaisedException const& e)
|
||||
{
|
||||
CPPUNIT_ASSERT(e.Message.startsWith("plain string"));
|
||||
CPPUNIT_ASSERT_EQUAL(u""_ustr, e.exceptionType);
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE(Execute);
|
||||
CPPUNIT_TEST(testThrows);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(Execute);
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
+55
-14
@@ -39,6 +39,7 @@
|
||||
#include <com/sun/star/script/Invocation.hpp>
|
||||
#include <com/sun/star/script/InvocationInfo.hpp>
|
||||
#include <com/sun/star/script/XInvocation2.hpp>
|
||||
#include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp>
|
||||
#include <com/sun/star/uno/Any.hxx>
|
||||
#include <com/sun/star/uno/Reference.hxx>
|
||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||
@@ -2435,6 +2436,56 @@ JSValue invokeUno(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst*
|
||||
return ret.release();
|
||||
});
|
||||
}
|
||||
|
||||
struct ExceptionData
|
||||
{
|
||||
OUString type;
|
||||
OUString message;
|
||||
};
|
||||
|
||||
ExceptionData extractExceptionData(JSContext* ctx, ValueRef const& err)
|
||||
{
|
||||
ExceptionData exc;
|
||||
bool haveMessage = false;
|
||||
if (JS_IsObject(err))
|
||||
{
|
||||
ValueRef const nameVal(ctx, JS_GetPropertyStr(ctx, err, "name"));
|
||||
if (JS_IsString(nameVal))
|
||||
{
|
||||
std::size_t n;
|
||||
UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, nameVal));
|
||||
if (p.get() != nullptr)
|
||||
{
|
||||
exc.type = OUString(p.get(), n);
|
||||
}
|
||||
}
|
||||
ValueRef const msgVal(ctx, JS_GetPropertyStr(ctx, err, "message"));
|
||||
if (JS_IsString(msgVal))
|
||||
{
|
||||
std::size_t n;
|
||||
UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, msgVal));
|
||||
if (p.get() != nullptr)
|
||||
{
|
||||
exc.message = OUString(p.get(), n);
|
||||
haveMessage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!haveMessage)
|
||||
{
|
||||
ValueRef const str(ctx, JS_ToString(ctx, err));
|
||||
if (!JS_IsException(str))
|
||||
{
|
||||
std::size_t n;
|
||||
UniqueCString16 const p(ctx, JS_ToCStringLenUTF16(ctx, &n, str));
|
||||
if (p.get() != nullptr)
|
||||
{
|
||||
exc.message = OUString(p.get(), n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return exc;
|
||||
}
|
||||
}
|
||||
|
||||
void jsuno::execute(OUString const& script)
|
||||
@@ -2497,7 +2548,7 @@ void jsuno::execute(OUString const& script)
|
||||
e = JS_NewClass(rt, getRuntimeData(rt)->moduleClassId, &moduleClass);
|
||||
assert(e == 0); //TODO
|
||||
auto const ctx = JS_NewContext(rt);
|
||||
std::optional<OUString> exc;
|
||||
std::optional<ExceptionData> exc;
|
||||
{
|
||||
ValueRef const global(ctx, JS_GetGlobalObject(ctx));
|
||||
getRuntimeData(ctx)->symbolIteratorAtom = JS_ValueToAtom(
|
||||
@@ -2560,18 +2611,7 @@ void jsuno::execute(OUString const& script)
|
||||
//TODO: reconstruct UNO exceptions
|
||||
ValueRef const err(ctx, JS_GetException(ctx));
|
||||
assert(!JS_IsException(err)); //TODO?
|
||||
ValueRef const str(ctx, JS_ToString(ctx, err));
|
||||
assert(!JS_IsException(str)); //TODO?
|
||||
std::size_t n1;
|
||||
UniqueCString16 const p1(ctx, JS_ToCStringLenUTF16(ctx, &n1, str));
|
||||
assert(p1.get() != nullptr); //TODO?
|
||||
ValueRef const stack(ctx, JS_GetPropertyStr(ctx, err, "stack"));
|
||||
assert(!JS_IsException(stack)); //TODO?
|
||||
std::size_t n2;
|
||||
UniqueCString16 const p2(ctx, JS_ToCStringLenUTF16(ctx, &n2, stack));
|
||||
assert(p2.get() != nullptr); //TODO?
|
||||
exc = OUString::Concat(std::u16string_view(p1.get(), n1)) + ": "
|
||||
+ std::u16string_view(p2.get(), n2);
|
||||
exc = extractExceptionData(ctx, err);
|
||||
}
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
@@ -2580,7 +2620,8 @@ void jsuno::execute(OUString const& script)
|
||||
JS_FreeRuntime(rt);
|
||||
if (exc)
|
||||
{
|
||||
throw css::uno::RuntimeException("JS exception: " + *exc);
|
||||
throw css::script::provider::ScriptExceptionRaisedException(
|
||||
exc->message, {}, u"<input>"_ustr, u"JavaScript"_ustr, -1, exc->type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user