Skip to content

Commit

Permalink
InternalBinding buffer and constants separated into new files
Browse files Browse the repository at this point in the history
Summary:
Moved the internal bindings' 'constants' and
'buffer' functionalities into a separate file. These
files contain a subset of the properties/functions
defined in node/src/node_buffer.cc and
node/src/node_constants.cc.

Had to update the BUCK file as well to prevent
the error 'untracked headers'.

Reviewed By: avp

Differential Revision: D29243913

fbshipit-source-id: a9812eed89f97817976836df6132426d99d84c5a
  • Loading branch information
adithiraofb authored and facebook-github-bot committed Jun 28, 2021
1 parent 705171d commit c5a9f7d
Show file tree
Hide file tree
Showing 3 changed files with 511 additions and 0 deletions.
14 changes: 14 additions & 0 deletions tools/node-hermes/InternalBindings/InternalBindings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "../RuntimeState.h"
#include "hermes/hermes.h"

namespace facebook {
jsi::Value bufferBinding(jsi::Runtime &rt, RuntimeState &rs);
jsi::Value constantsBinding(jsi::Runtime &rt, RuntimeState &rs);
} // namespace facebook
118 changes: 118 additions & 0 deletions tools/node-hermes/InternalBindings/buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "InternalBindings.h"
#include "hermes/hermes.h"

using namespace facebook;

/// Creates a new array buffer by calling the JS constructor. If
/// the buffer was not able to be constructed, throws an error.
static jsi::ArrayBuffer newArrayBuffer(jsi::Runtime &rt, size_t size) {
jsi::Object retBufferAsObject = rt.global()
.getPropertyAsFunction(rt, "ArrayBuffer")
.callAsConstructor(rt, (int)size)
.asObject(rt);
if (!retBufferAsObject.isArrayBuffer(rt))
throw jsi::JSError(rt, "Could not construct ArrayBuffer");

return retBufferAsObject.getArrayBuffer(rt);
}

/// Returns the the utf8 length of a jsi::String that is passed in as a
/// jsi::Value. Note: this function is currently not needed by fs.js and
/// was primarily used for initial testing purposes.
static jsi::Value byteLengthUtf8(
jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *args,
size_t count) {
if (count < 1) {
throw jsi::JSError(rt, "Not enough arguments passed in to byteLengthUtf8.");
}
if (!args[0].isString()) {
throw jsi::JSError(rt, "byteLengthUtf8 must be called on a string object");
}

return jsi::Value(rt, (int)args[0].toString(rt).utf8(rt).length());
}

/// Given the caller jsi::Value, which should translate to a Buffer object,
/// returns a jsi::String representing the sliced version of the array.
static jsi::Value utf8Slice(
jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *args,
size_t count) {
jsi::Object thisBuffer =
thisValue.asObject(rt).getPropertyAsObject(rt, "buffer");
if (!thisBuffer.isArrayBuffer(rt)) {
throw jsi::JSError(
rt,
"UTF8Slice must be called on an object that contains an arraybuffer.");
}
if (count < 2) {
throw jsi::JSError(rt, "Not enough arguments passed in to utf8Slice.");
}
size_t start = args[0].asNumber();
size_t len = args[1].asNumber();

jsi::ArrayBuffer existingArray = thisBuffer.getArrayBuffer(rt);
if (start + len > existingArray.size(rt)) {
throw jsi::JSError(rt, "Index out of range");
}

return jsi::String::createFromUtf8(rt, existingArray.data(rt) + start, len);
}

/// Creates an ArrayBuffer the size of an uint32_t and returns it. Used for
/// internal buffer purposes. This is implemented in v8 with a private object.
static jsi::Value getZeroFillToggle(
jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *args,
size_t count) {
return newArrayBuffer(rt, sizeof(uint32_t));
}

/// Initializes a new JS function given a function pointer to the c++ function.
static void defineJSFunction(
jsi::Runtime &rt,
jsi::Value (*functionPtr)(
jsi::Runtime &,
const jsi::Value &,
const jsi::Value *,
size_t),
llvh::StringRef functionName,
size_t numArgs,
jsi::Object &buffer) {
jsi::String jsiFunctionName = jsi::String::createFromAscii(rt, functionName);
jsi::Object JSFunction = jsi::Function::createFromHostFunction(
rt,
jsi::PropNameID::forString(rt, jsiFunctionName),
numArgs,
functionPtr);
buffer.setProperty(rt, jsiFunctionName, JSFunction);
}

/// Adds the 'buffer' object as a property of internalBinding.
/// Initializes the relevant internalBinding('buffer') functions to get
/// Buffer.alloc, Buffer.concat and Buffer.toString working in buffer.js.
jsi::Value facebook::bufferBinding(jsi::Runtime &rt, RuntimeState &rs) {
jsi::Object buffer{rt};

defineJSFunction(rt, byteLengthUtf8, "byteLengthUtf8", 1, buffer);
defineJSFunction(rt, getZeroFillToggle, "getZeroFillToggle", 0, buffer);
defineJSFunction(rt, utf8Slice, "utf8Slice", 2, buffer);

jsi::Value kMaxLength{(double)(uint64_t{2} << 32)};
buffer.setProperty(rt, "kMaxLength", kMaxLength);

jsi::String bufferLabel = jsi::String::createFromAscii(rt, "Buffer");
rs.setInternalBindingProp(bufferLabel, std::move(buffer));
return rs.getInternalBindingProp(bufferLabel);
}
Loading

0 comments on commit c5a9f7d

Please sign in to comment.