Skip to content

Commit

Permalink
Merge branch 'main' into Xmader/chore/wheel-macos-version-support
Browse files Browse the repository at this point in the history
  • Loading branch information
zollqir authored Sep 6, 2024
2 parents ab8ba46 + 2d19e25 commit a5634c3
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 66 deletions.
8 changes: 7 additions & 1 deletion .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ aae30e864449442cf0b04e94f8a242b1b667de9a
16dc3153b3cb684ca72445ed058babc8f5d97f42

# chore(linting): lint all C++ files
58cd4b45777b046f03a63255c1d93e289e1cab5e
58cd4b45777b046f03a63255c1d93e289e1cab5e

# chore(linting): lint PyBytesProxyHandler.cc
d540ed6e0edfe9538dc726cf587dfb2cc76dde34

# chore(linting): lint PyObjectProxyHandler.cc
1d45ea98e42294cce16deec5454725d4de36f59f
7 changes: 0 additions & 7 deletions .github/workflows/test-and-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,6 @@ jobs:
matrix:
os: [ 'ubuntu-20.04', 'macos-12', 'macos-14', 'windows-2022', 'pi' ]
python_version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ]
exclude:
# actions/setup-python: The version '3.8'/'3.9' with architecture 'arm64' was not found for macOS.
# see https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
- os: 'macos-14'
python_version: '3.8'
- os: 'macos-14'
python_version: '3.9'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/update-mozcentral-version.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: 'Create pull requests to update mozilla-central version to the latest'

on:
schedule:
- cron: "00 14 * * 1" # run every Monday at 14:00 UTC (10:00 Eastern Daylight Time)
- cron: "00 14 */100,1-7 * 1" # run on the first Monday of each month at 14:00 UTC (10:00 Eastern Daylight Time)
# See https://blog.healthchecks.io/2022/09/schedule-cron-job-the-funky-way/
workflow_call:
workflow_dispatch: # or you can run it manually

Expand Down Expand Up @@ -33,8 +34,10 @@ jobs:
add-paths: mozcentral.version
commit-message: |
chore(deps): upgrade SpiderMonkey to `${{ env.MOZCENTRAL_VERSION }}`
author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
branch: chore/upgrade-spidermonkey-to-${{ env.MOZCENTRAL_VERSION_SHORT }}
title: Upgrade SpiderMonkey to mozilla-central commit `${{ env.MOZCENTRAL_VERSION }}`
body: |
Changeset: https://hg.mozilla.org/mozilla-central/rev/${{ env.MOZCENTRAL_VERSION }}
labels: dependencies
assignees: Xmader
16 changes: 10 additions & 6 deletions include/JSStringProxy.hh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include <Python.h>

#include <unordered_set>

/**
* @brief The typedef for the backing store that will be used by JSStringProxy objects. All it contains is a pointer to the JSString
*
Expand All @@ -24,6 +26,8 @@ typedef struct {
JS::PersistentRootedValue *jsString;
} JSStringProxy;

extern std::unordered_set<JSStringProxy *> jsStringProxies; // a collection of all JSStringProxy objects, used during a GCCallback to ensure they continue to point to the correct char buffer

/**
* @brief This struct is a bundle of methods used by the JSStringProxy type
*
Expand All @@ -37,7 +41,7 @@ public:
*/
static void JSStringProxy_dealloc(JSStringProxy *self);

/**
/**
* @brief copy protocol method for both copy and deepcopy
*
* @param self - The JSObjectProxy
Expand All @@ -49,13 +53,13 @@ public:
// docs for methods, copied from cpython
PyDoc_STRVAR(stringproxy_deepcopy__doc__,
"__deepcopy__($self, memo, /)\n"
"--\n"
"\n");
"--\n"
"\n");

PyDoc_STRVAR(stringproxy_copy__doc__,
"__copy__($self, /)\n"
"--\n"
"\n");
"__copy__($self, /)\n"
"--\n"
"\n");

/**
* @brief Struct for the other methods
Expand Down
2 changes: 1 addition & 1 deletion mozcentral.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8a28ad54f9f516c41ceddfa7ea32368fccf4a0eb
a283127a5d0aa005c54d339e8ca27414b55f079b
3 changes: 2 additions & 1 deletion src/JSStringProxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@

#include "include/StrType.hh"


std::unordered_set<JSStringProxy *> jsStringProxies;
extern JSContext *GLOBAL_CX;


void JSStringProxyMethodDefinitions::JSStringProxy_dealloc(JSStringProxy *self)
{
jsStringProxies.erase(self);
delete self->jsString;
}

Expand Down
44 changes: 22 additions & 22 deletions src/PyBytesProxyHandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,30 @@ static bool array_valueOf(JSContext *cx, unsigned argc, JS::Value *vp) {
return false;
}

JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::RootedObject rootedArrayBuffer(cx, arrayBuffer->get());

auto byteLength = JS::GetArrayBufferByteLength(rootedArrayBuffer);

bool isSharedMemory;
bool isSharedMemory;
JS::AutoCheckCannotGC autoNoGC(cx);
uint8_t *data = JS::GetArrayBufferData(rootedArrayBuffer, &isSharedMemory, autoNoGC);

size_t numberOfDigits = 0;
for (size_t i = 0; i < byteLength; i++) {
numberOfDigits += data[i] < 10 ? 1 : data[i] < 100 ? 2 : 3;
numberOfDigits += data[i] < 10 ? 1 : data[i] < 100 ? 2 : 3;
}
const size_t STRING_LENGTH = byteLength + numberOfDigits;
JS::Latin1Char* buffer = (JS::Latin1Char *)malloc(sizeof(JS::Latin1Char) * STRING_LENGTH);
JS::Latin1Char *buffer = (JS::Latin1Char *)malloc(sizeof(JS::Latin1Char) * STRING_LENGTH);

size_t charIndex = 0;
sprintf((char*)&buffer[charIndex], "%d", data[0]);
snprintf((char *)&buffer[charIndex], 4, "%d", data[0]);
charIndex += data[0] < 10 ? 1 : data[0] < 100 ? 2 : 3;

for (size_t dataIndex = 1; dataIndex < byteLength; dataIndex++) {
buffer[charIndex] = ',';
charIndex++;
sprintf((char*)&buffer[charIndex], "%d", data[dataIndex]);
snprintf((char *)&buffer[charIndex], 4, "%d", data[dataIndex]);
charIndex += data[dataIndex] < 10 ? 1 : data[dataIndex] < 100 ? 2 : 3;
}

Expand Down Expand Up @@ -84,7 +84,7 @@ static bool iterator_next(JSContext *cx, unsigned argc, JS::Value *vp) {
JS::RootedObject thisObj(cx);
if (!args.computeThis(cx, &thisObj)) return false;

JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(thisObj, BytesIteratorSlotIteratedObject);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(thisObj, BytesIteratorSlotIteratedObject);
JS::RootedObject rootedArrayBuffer(cx, arrayBuffer->get());

JS::RootedValue rootedNextIndex(cx, JS::GetReservedSlot(thisObj, BytesIteratorSlotNextIndex));
Expand Down Expand Up @@ -112,7 +112,7 @@ static bool iterator_next(JSContext *cx, unsigned argc, JS::Value *vp) {
if (!JS_SetProperty(cx, result, "done", done)) return false;

if (itemKind == ITEM_KIND_VALUE) {
bool isSharedMemory;
bool isSharedMemory;
JS::AutoCheckCannotGC autoNoGC(cx);
uint8_t *data = JS::GetArrayBufferData(rootedArrayBuffer, &isSharedMemory, autoNoGC);

Expand All @@ -125,7 +125,7 @@ static bool iterator_next(JSContext *cx, unsigned argc, JS::Value *vp) {
JS::RootedValue rootedNextIndex(cx, JS::Int32Value(nextIndex));
items[0].set(rootedNextIndex);

bool isSharedMemory;
bool isSharedMemory;
JS::AutoCheckCannotGC autoNoGC(cx);
uint8_t *data = JS::GetArrayBufferData(rootedArrayBuffer, &isSharedMemory, autoNoGC);

Expand Down Expand Up @@ -216,8 +216,8 @@ static bool array_iterator_func(JSContext *cx, unsigned argc, JS::Value *vp, int
if (!JS::Construct(cx, constructor_val, JS::HandleValueArray::empty(), &obj)) return false;
if (!obj) return false;

JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);

JS::SetReservedSlot(obj, BytesIteratorSlotIteratedObject, JS::PrivateValue(arrayBuffer));
JS::SetReservedSlot(obj, BytesIteratorSlotNextIndex, JS::Int32Value(0));
JS::SetReservedSlot(obj, BytesIteratorSlotItemKind, JS::Int32Value(itemKind));
Expand Down Expand Up @@ -253,13 +253,13 @@ bool PyBytesProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleI
JS::HandleValue v, JS::HandleValue receiver,
JS::ObjectOpResult &result) const {

// block all modifications
// block all modifications

PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);

PyErr_Format(PyExc_TypeError,
"'%.100s' object has only read-only attributes",
Py_TYPE(self)->tp_name);
"'%.100s' object has only read-only attributes",
Py_TYPE(self)->tp_name);

return result.failReadOnly();
}
Expand Down Expand Up @@ -298,7 +298,7 @@ bool PyBytesProxyHandler::getOwnPropertyDescriptor(

// "length" and "byteLength" properties have the same value
if ((JS_StringEqualsLiteral(cx, idString, "length", &isProperty) && isProperty) || (JS_StringEqualsLiteral(cx, id.toString(), "byteLength", &isProperty) && isProperty)) {
JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);

JS::RootedObject rootedArrayBuffer(cx, arrayBuffer->get());

Expand All @@ -314,7 +314,7 @@ bool PyBytesProxyHandler::getOwnPropertyDescriptor(

// "buffer" property
if (JS_StringEqualsLiteral(cx, idString, "buffer", &isProperty) && isProperty) {
JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);

desc.set(mozilla::Some(
JS::PropertyDescriptor::Data(
Expand Down Expand Up @@ -392,10 +392,10 @@ bool PyBytesProxyHandler::getOwnPropertyDescriptor(
// item
Py_ssize_t index;
if (idToIndex(cx, id, &index)) {
JS::PersistentRootedObject* arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::PersistentRootedObject *arrayBuffer = JS::GetMaybePtrFromReservedSlot<JS::PersistentRootedObject>(proxy, OtherSlot);
JS::RootedObject rootedArrayBuffer(cx, arrayBuffer->get());

bool isSharedMemory;
bool isSharedMemory;
JS::AutoCheckCannotGC autoNoGC(cx);
uint8_t *data = JS::GetArrayBufferData(rootedArrayBuffer, &isSharedMemory, autoNoGC);

Expand All @@ -406,7 +406,7 @@ bool PyBytesProxyHandler::getOwnPropertyDescriptor(
));

return true;
}
}

PyObject *attrName = idToKey(cx, id);
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
Expand Down
4 changes: 2 additions & 2 deletions src/PyListProxyHandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2099,8 +2099,8 @@ void PyListProxyHandler::finalize(JS::GCContext *gcx, JSObject *proxy) const {
// We cannot call Py_DECREF here when shutting down as the thread state is gone.
// Then, when shutting down, there is only on reference left, and we don't need
// to free the object since the entire process memory is being released.
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
if (Py_REFCNT(self) > 1) {
if (!_Py_IsFinalizing()) {
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
Py_DECREF(self);
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/PyObjectProxyHandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ bool PyObjectProxyHandler::handleGetOwnPropertyDescriptor(JSContext *cx, JS::Han
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc, PyObject *item) {
// see if we're calling a function
if (id.isString()) {
JS::RootedString idString(cx, id.toString());
const char *methodName = JS_EncodeStringToUTF8(cx, idString).get();
JS::UniqueChars idString = JS_EncodeStringToUTF8(cx, JS::RootedString(cx, id.toString()));
const char *methodName = idString.get();

if (!strcmp(methodName, "toString") || !strcmp(methodName, "toLocaleString") || !strcmp(methodName, "valueOf")) {
JS::RootedObject objectPrototype(cx);
if (!JS_GetClassPrototype(cx, JSProto_Object, &objectPrototype)) {
Expand Down Expand Up @@ -87,8 +88,8 @@ void PyObjectProxyHandler::finalize(JS::GCContext *gcx, JSObject *proxy) const {
// We cannot call Py_DECREF here when shutting down as the thread state is gone.
// Then, when shutting down, there is only on reference left, and we don't need
// to free the object since the entire process memory is being released.
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
if (Py_REFCNT(self) > 1) {
if (!_Py_IsFinalizing()) {
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
Py_DECREF(self);
}
}
Expand All @@ -109,12 +110,12 @@ bool PyObjectProxyHandler::ownPropertyKeys(JSContext *cx, JS::HandleObject proxy
}

return handleOwnPropertyKeys(cx, nonDunderKeys, PyList_Size(nonDunderKeys), props);
}
}
else {
if (PyErr_Occurred()) {
PyErr_Clear();
PyErr_Clear();
}

return handleOwnPropertyKeys(cx, PyList_New(0), 0, props);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/StrType.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ PyObject *StrType::proxifyString(JSContext *cx, JS::HandleValue strVal) {
JS::RootedObject obj(cx);
pyString->jsString = new JS::PersistentRootedValue(cx);
pyString->jsString->setString((JSString *)lstr);
jsStringProxies.insert(pyString);

// Initialize as legacy string (https://github.com/python/cpython/blob/v3.12.0b1/Include/cpython/unicodeobject.h#L78-L93)
// see https://github.com/python/cpython/blob/v3.11.3/Objects/unicodeobject.c#L1230-L1245
Expand Down
Loading

0 comments on commit a5634c3

Please sign in to comment.