Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
Jarred Sumner
2023-08-19 17:46:59 -07:00
committed by GitHub
parent 86ad015147
commit 196620183f
7 changed files with 88 additions and 10 deletions

View File

@@ -20,6 +20,7 @@
"${workspaceFolder}/src/js/out",
"${workspaceFolder}/src/deps/boringssl/include/",
"${workspaceFolder}/src/deps",
"${workspaceFolder}/src/napi/*",
"${workspaceFolder}/src/deps/uws/uSockets/src"
],
"browse": {
@@ -32,6 +33,8 @@
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/WTF/Headers/**",
"${workspaceFolder}/src/bun.js/WebKit/WebKitBuild/Release/bmalloc/Headers/**",
"${workspaceFolder}/src/bun.js/bindings/*",
"${workspaceFolder}/src/bun.js/bindings/*",
"${workspaceFolder}/src/napi/*",
"${workspaceFolder}/src/bun.js/bindings/sqlite/",
"${workspaceFolder}/src/bun.js/bindings/webcrypto/",
"${workspaceFolder}/src/bun.js/bindings/webcore/",

View File

@@ -1244,19 +1244,31 @@ JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSObject* constructorTarget = asObject(callFrame->jsCallee());
JSObject* newTarget = asObject(callFrame->newTarget());
NapiClass* napi = jsDynamicCast<NapiClass*>(constructorTarget);
while (!napi && constructorTarget) {
constructorTarget = constructorTarget->getPrototypeDirect().getObject();
napi = jsDynamicCast<NapiClass*>(constructorTarget);
}
NapiClass* napi = jsDynamicCast<NapiClass*>(newTarget);
if (UNLIKELY(!napi)) {
JSC::throwVMError(globalObject, scope, JSC::createTypeError(globalObject, "NapiClass constructor called on an object that is not a NapiClass"_s));
return JSC::JSValue::encode(JSC::jsUndefined());
}
NapiPrototype* prototype = JSC::jsDynamicCast<NapiPrototype*>(napi->getDirect(vm, vm.propertyNames->prototype));
NapiPrototype* prototype = JSC::jsDynamicCast<NapiPrototype*>(napi->getIfPropertyExists(globalObject, vm.propertyNames->prototype));
RETURN_IF_EXCEPTION(scope, {});
if (!prototype) {
JSC::throwVMError(globalObject, scope, JSC::createTypeError(globalObject, "NapiClass constructor is missing the prototype"_s));
return JSC::JSValue::encode(JSC::jsUndefined());
}
auto* subclass = prototype->subclass(globalObject, newTarget);
RETURN_IF_EXCEPTION(scope, {});
callFrame->setThisValue(subclass);
size_t count = callFrame->argumentCount();
MarkedArgumentBuffer args;
@@ -1266,7 +1278,6 @@ JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
}
}
callFrame->setThisValue(prototype->subclass(newTarget));
napi->constructor()(globalObject, callFrame);
RETURN_IF_EXCEPTION(scope, {});

View File

@@ -213,15 +213,19 @@ public:
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
NapiPrototype* subclass(JSC::JSObject* newTarget)
NapiPrototype* subclass(JSC::JSGlobalObject* globalObject, JSC::JSObject* newTarget)
{
auto& vm = this->vm();
auto* structure = InternalFunction::createSubclassStructure(globalObject(),
newTarget,
this->structure());
auto scope = DECLARE_THROW_SCOPE(vm);
auto* targetFunction = jsCast<JSFunction*>(newTarget);
FunctionRareData* rareData = targetFunction->ensureRareData(vm);
auto* prototype = newTarget->get(globalObject, vm.propertyNames->prototype).getObject();
RETURN_IF_EXCEPTION(scope, nullptr);
auto* structure = rareData->createInternalFunctionAllocationStructureFromBase(vm, globalObject, prototype, this->structure());
RETURN_IF_EXCEPTION(scope, nullptr);
NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
footprint->finishCreation(vm);
return footprint;
RELEASE_AND_RETURN(scope, footprint);
}
NapiRef* napiRef = nullptr;

Binary file not shown.

53
test/js/third_party/resvg/bbox.test.js vendored Normal file
View File

@@ -0,0 +1,53 @@
import { test, expect } from "bun:test";
import { Resvg } from "@resvg/resvg-js";
const svg = `<svg viewBox="-40 0 180 260" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g fill="green" transform="rotate(-10 50 100) translate(-36 45.5) skewX(40) scale(1 0.5)">
<path id="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" />
</g>
<use xlink:href="#heart" fill="none" stroke="red" stroke-width="1" />
</svg>`;
for (let Class of [
Resvg,
// Test that subclasses work as well.
class ResvgSubclass extends Resvg {
constructor(...args) {
super(...args);
}
iShouldExist() {
return true;
}
},
]) {
test(`bbox ${Class.name}`, () => {
const opts = {
fitTo: {
mode: "width",
value: 500,
},
font: {
loadSystemFonts: false,
},
};
const resvg = new Class(svg, opts);
const bbox = resvg.getBBox();
expect(resvg.width).toBe(180);
expect(resvg.height).toBe(260);
if (bbox) resvg.cropByBBox(bbox);
const pngData = resvg.render();
expect(bbox.width).toBe(112.20712208389321);
expect(bbox.height).toBe(81);
expect(pngData.width).toBe(500);
expect(pngData.height).toBe(362);
if (Class !== Resvg) {
expect(resvg).toHaveProperty("iShouldExist");
expect(resvg.iShouldExist()).toBeTrue();
}
});
}

View File

@@ -0,0 +1,6 @@
{
"name": "bun-integration-test-resvg",
"dependencies": {
"@resvg/resvg-js": "2.4.1"
}
}

View File

@@ -25,6 +25,7 @@
"pg-connection-string": "2.6.1",
"postgres": "3.3.5",
"prisma": "5.1.1",
"@resvg/resvg-js": "2.4.1",
"socket.io": "4.7.1",
"socket.io-client": "4.7.1",
"supertest": "6.3.3",