Skip to content

Commit

Permalink
Fixes #172
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Aug 20, 2023
1 parent 86ad015 commit 3561d47
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -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/",
Expand Down
19 changes: 15 additions & 4 deletions src/bun.js/bindings/napi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1244,18 +1244,30 @@ 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;
Expand All @@ -1266,7 +1278,6 @@ JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
}
}

callFrame->setThisValue(prototype->subclass(newTarget));
napi->constructor()(globalObject, callFrame);
RETURN_IF_EXCEPTION(scope, {});

Expand Down
14 changes: 9 additions & 5 deletions src/bun.js/bindings/napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,19 @@ class NapiPrototype : public JSC::JSDestructibleObject {
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;
Expand Down
Binary file modified test/bun.lockb
Binary file not shown.
53 changes: 53 additions & 0 deletions test/js/third_party/resvg/bbox.test.js
Original file line number Diff line number Diff line change
@@ -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();
}
});
}
6 changes: 6 additions & 0 deletions test/js/third_party/resvg/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "bun-integration-test-resvg",
"dependencies": {
"@resvg/resvg-js": "2.4.1"
}
}
1 change: 1 addition & 0 deletions test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit 3561d47

Please sign in to comment.