Skip to content

Conversation

@faunks
Copy link
Contributor

@faunks faunks commented Nov 27, 2025

TheShovel, what's up pookie ;P

TheShovel, what's up pookie ;P
@vercel
Copy link

vercel bot commented Nov 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
penguinmod-extensions-gallery Ready Ready Preview Dec 24, 2025 1:34pm

@JeremyGamer13 JeremyGamer13 added the extension update This updates an already existing extension label Nov 27, 2025
@TheShovel
Copy link
Collaborator

reading an empty blob returns the penguinmod home page. It shouldnt do that. Make it return nothing.

reading anything as an image returns a object that cant be used because of scratch parsing.

fix these
Screenshot_20251128_150143_Firefox.png
Screenshot_20251128_150203_Firefox.png


if (mime.startsWith("text/") || mime === "application/json") {
const text = await blob.text();
return mime === "application/json" ? text : text;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return text, here. On second thought, condense this into return await blob.text();.

const response = await fetch(url);
const blob = await response.blob();

if (!url.startsWith("blob:")) return "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you only just now checking if the url is actually a blob? Check before you fetch.

{
opcode: "readBlob",
blockType: Scratch.BlockType.REPORTER,
text: "read blob [URL] as a [TYPE]",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This casing on the reporter here is inconsistent with the other blocks.

return btoa(binary);
}

return readBlobContent(args.URL, args.TYPE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure if this is all you're doing, you don't even need to have another function inside here, just make the function root async; in any case, this will be returning a promise, so it really doesn't matter that you did it this way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another note about this because I feel like this is important, I'm asking for the method to be made async and for it to directly return rather than routing it through another function. This is all around more readable, at least in my opinion.

async readBlob(args, util) {
  ...
  return btoa(binary);
}

feel free to disagree, here, though.

Comment on lines 152 to 158
const buffer = await blob.arrayBuffer();
const bytes = new Uint8Array(buffer);

let binary = "";
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could just be me, but I think there might be more efficient ways of converting an array buffer into a string. Maybe TextDecoder, or utilizing a DataView instead of Uint8Array. One thing that I know for a fact is that V8 (Chrome) handles DataView more efficiently than Uint8Array: https://v8.dev/blog/dataview. Not sure on the state of Firefox, here, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is done! thanks for the feedback btw, I was kind of rushing adding some of the stuff (to which I apologize), from now on I will try to do stuff and put more work into it(which may slow things down because the main reason of which made me rush things up is a really tight time schedule). If you have any other stuff you want me to add I would be more than happy to do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could just be me, but I think there might be more efficient ways of converting an array buffer into a string. Maybe TextDecoder, or utilizing a DataView instead of Uint8Array. One thing that I know for a fact is that V8 (Chrome) handles DataView more efficiently than Uint8Array: https://v8.dev/blog/dataview. Not sure on the state of Firefox, here, though.

That blog article says otherwise? "We found that our new DataView implementation provides almost the same performance as TypedArrays when accessing data aligned in the native endianness (little-endian on Intel processors)"

I couldn't remove that one loop and I spent a long time trying to do so, if you have any more stuff you would like me to change I would be more than happy to do so
readBlob(args, util) {
async function readBlobContent(url, mime) {

if (!url.startsWith("blob:")) return ""; // I WOULD return "Url Error", but it would make it a bit harder to track if an output has been returned or not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could throw an error. So throw new URIError("must be a blob url"); or something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks. I've just added it so it would do that (I hope it also acts as a return method)

return await blob.text();
}

const buffer = await blob.arrayBuffer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After doing a bit of looking at the MDN documentation for Blob, there may be a way of doing this with a readable stream, although I'd need to check how efficient that is. Also quick note that the text method doesn't seem to require text to actually be text, so it can pretty much be anything and still be interpreted as text.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could also be wrong about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's worth spending time on concidering the extension already runs really fast and uploading bigger files would be an issue by it's one to be honest, I think it would be better for this chunk of the code to be as is instead of spending time on how we could improve it right now, a think that we can and probably may happen at some point.

for (let i = 0; i < view.byteLength; i++) {
binary += String.fromCharCode(view.getUint8(i));
}
return btoa(binary);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of reading the text as Base64? PenguinMod will be able to handle direct binary-encoded data, pretty sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think that outputting it as b64 could be considered unexpected behavior, mostly because input isn't given in base 64.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so what do you recommend the output being?, if you're just saying to output the raw data then sure I would just return it if you like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think outputting the raw information is the best option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just spent like 2 hours, scratch cannot handle raw bytes,
image
this just destroyes the image.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats not a scratch thing though, thats the javascript

The block explicitly casts any input to a string before saving it to an object URL. Whether this is Scratch's or JavaScript's fault is, for all purposes, entirely irrelevant. Non-JS string safe characters cannot be added to an object URL due to the limitations of this extension, and so no non-JS string safe characters couldn't possibly be read from an object URL, unless someone is utilizing another extension that allows for that, or are directly encoding things to an object URL through a JavaScript eval extension. That was my point in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was the point of my reply, and what you said there doesnt match what you say now in how you lay it out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wgat

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read should not be using string btoa, js strings will naturally corrupt binary data due to how they work
if its intention is just to return some handle for the data that can be referenced later, this will need a custom base64 encoder
however if its intention is instead to provide data in a way the project can read all on its own, it must be in a raw byte format, such as 0,255,127,63,31,15,7,3,1
i am fairly certain that the later is the intention, not the former, since the block provides types for things like gltf and obj, where the intent of loading such a file is likely specifically to get something that the project intends to manually render, and also provides formats like json and text as the actual data rather then as a base64 string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was the point of my reply, and what you said there doesnt match what you say now in how you lay it out

That's what the intended meaning of my point was, if that doesn't come across at all then that's my bad.

Here's some bullet points on what this does:

* Allow extension users to choose what they want to be outputted, rather
  than deciding automatically based on the MIME.
* Correct base64 encoding: encoding through first writing it to a string
  is not only a relatively slow way of doing such, but is also not safe,
  due to the potential for data loss.
* Added 4 encoding types, available in both the read and write blocks
  for blob URLs: base 64, data URL, plain text, byte array.
  * Base 64 reads it as base 64; note: not a string encoded to base 64,
    but as binary data that was base 64 encoded.
  * Data URL resolves the data URL and uses its content to write to the
    object URL.
  * Plaintext just takes in the input as plaintext, just as it was done
    before.
  * Byte array takes in an array of numbers that are between 0 and 255
    and reads it as a string of bytes. Outputted as a JSON string so as
    to be compatible with other extensions such as Arrays.
@Steve0Greatness
Copy link
Contributor

Feel like I should properly mention that I made a PR on your fork that fixes the most major issues I have with this PR: faunks#1. More details are available on that page.

Use encoding types instead of just using plaintext.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension update This updates an already existing extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants