Search code examples
javascriptc++qtv8arraybuffer

Function to read binary files using v8


I am using QT and v8 to develop a Javascript interpreter.

I need to create a function that can read a binary file from the specified path.

This is my C++ code to do that:

void ScriptThread::ReadFile(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    if (v8::V8::IsExecutionTerminating(args.GetIsolate()) || instance->m_killFlag)
        return;
    v8::HandleScopehandle_scope(args.GetIsolate());
    if (args.Length() != 1)
    {
        args.GetIsolate()->ThrowException(
            v8::String::NewFromUtf8(args.GetIsolate(), "Bad parameters"));
        return;
    }

    v8::String::Utf8Value str(args[0]);
    QString filepath = *str;

    QFile file(filepath);
    if (!file.open(QFile::ReadOnly))
    {
        return;
    }

    QByteArray data = file.readAll();

    v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(args.GetIsolate(), (void*)data.data(), data.size());

    args.GetReturnValue().Set(ab);
}

The problem is that after calling this function in Javascript, the ArrayBuffer in the js file contains random data instead of the content of the file.

Here is my JS code:

var buffer = ReadFile("D:/Temp/myfolder/ascii.txt")

Log(buffer)

var view = new Uint8Array(buffer)

Log(view)
Log(String.fromCharCode.apply(null, view))

D:/Temp/myfolder/ascii.txt:

ABCDEF

and the output of my JS after running the script several times without changing the file path:

2016-09-15 12:42:35.847  Script Info    [object ArrayBuffer]
2016-09-15 12:42:35.847  Script Info    200,29,125,195,254,136
2016-09-15 12:42:35.847  Script Info    È}Ãþ
2016-09-15 12:42:35.847  Info           Script Stopped

2016-09-15 12:43:41.543  Script Info    [object ArrayBuffer]
2016-09-15 12:43:41.543  Script Info    238,254,238,254,238,254
2016-09-15 12:43:41.543  Script Info    îþîþîþ
2016-09-15 12:43:41.543  Info           Script Stopped

2016-09-15 12:47:19.588  Script Info    [object ArrayBuffer]
2016-09-15 12:47:19.588  Script Info    m
2016-09-15 12:47:19.588  Script Info    30,25,109,30,0,0
2016-09-15 12:47:19.588  Info           Script Stopped

I checked the data inside v8::ArrayBuffer from my cpp file.

I can't use String because the function is required to read non human readable files and I don't want to include node.js in my project.

Is somehow the ArrayBuffer GCed before return? Or am I out of the scope somehow? Can you guys help me?

Thanks!


Solution

  • I don't know much about QT, but it looks like you're pointing the array buffer to data for a variable on the stack

    QByteArray data = file.readAll();
    

    that likely (I don't know QByteArray) gets cleaned up after you return from creating the array buffer.

    From http://v8.paulfryzel.com/docs/master/classv8_1_1_array_buffer.html:

    Create a new ArrayBuffer over an existing memory block. The created array buffer is by default immediately in externalized state. The memory block will not be reclaimed when a created ArrayBuffer is garbage-collected.

    So I'm pretty sure it's relying on you to make sure the memory it points to remains valid, which I don't think you're doing.