بنقرة واحدة
nativefunction
Implement a new JavaScript native/builtin function (e.g. Array.from, String.prototype.trim, Math.abs).
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Implement a new JavaScript native/builtin function (e.g. Array.from, String.prototype.trim, Math.abs).
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | nativefunction |
| description | Implement a new JavaScript native/builtin function (e.g. Array.from, String.prototype.trim, Math.abs). |
Implement a new JavaScript built-in/native function in the Arc runtime.
The user will specify the function, e.g. /nativefunction Array.from or /nativefunction String.prototype.trim.
Before writing any code, study how existing JS engines implement this function. This is critical — JS semantics are full of subtle edge cases.
quickjs.c:
https://raw.githubusercontent.com/bellard/quickjs/master/quickjs.c or search GitHubengine262/src/:
https://github.com/engine262/engine262vendor/test262/test/built-ins/ for the relevant directorySummarize the key semantics, edge cases, and spec requirements before proceeding.
Touch these files in order:
src/arc/vm/value.gleam — Add variant to the module's NativeFn typeNativeFn is split per-module. Find the right type and add a variant:
| JS Object | Type in value.gleam |
|---|---|
| Array | ArrayNativeFn |
| Object | ObjectNativeFn |
| String | StringNativeFn |
| Number | NumberNativeFn |
| Boolean | BooleanNativeFn |
| Math | MathNativeFn |
| JSON | JsonNativeFn |
| Map/Set/WeakMap/WeakSet | MapNativeFn / SetNativeFn / etc. |
| RegExp | RegExpNativeFn |
| Error + subtypes | ErrorNativeFn |
| Arc (engine-specific) | ArcNativeFn |
Naming convention (no Native prefix on variants):
pub type ArrayNativeFn {
// ... existing variants ...
ArrayFrom // Array.from — static
ArrayPrototypeMap // Array.prototype.map — instance
ArrayConstructor // Array() / new Array() — constructor
}
These are plain tag variants with no GC implications — no other value.gleam changes needed.
New global (e.g. Date, Proxy): create a new <Name>NativeFn type, then add a wrapper variant to the top-level NativeFn type:
pub type NativeFn {
// ... existing ...
DateNative(DateNativeFn)
}
src/arc/vm/builtins/<module>.gleam — Implement + dispatchFind or create the module:
| JS Object | Module |
|---|---|
| Array | builtins/array.gleam |
| Object | builtins/object.gleam |
| String | builtins/string.gleam |
| Number | builtins/number.gleam |
| Math | builtins/math.gleam |
| JSON | builtins/json.gleam |
| Map/Set | builtins/map.gleam / builtins/set.gleam |
| RegExp | builtins/regexp.gleam |
| Error | builtins/error.gleam |
| Arc | builtins/arc.gleam |
| New globals | NEW builtins/<name>.gleam |
dispatch functionEvery module has pub fn dispatch(native, args, this, state) that routes variants to implementations:
pub fn dispatch(
native: ArrayNativeFn,
args: List(JsValue),
this: JsValue,
state: State,
) -> #(State, Result(JsValue, JsValue)) {
case native {
// ... existing cases ...
ArrayPrototypeMap -> array_map(this, args, state)
ArrayFrom -> array_from(args, state)
}
}
Signature: takes State, returns #(State, Result(JsValue, JsValue)):
fn array_map(
this: JsValue,
args: List(JsValue),
state: State,
) -> #(State, Result(JsValue, JsValue)) {
use _ref, length, elements, state <- require_array(this, state)
use cb, this_arg, state <- require_callback(args, state)
// ... spec steps ...
}
Static methods omit this; constructors take args and return the new instance.
initAdd to the common.alloc_methods list:
pub fn init(h: Heap, object_proto: Ref, function_proto: Ref) -> #(Heap, BuiltinType) {
let #(h, proto_methods) =
common.alloc_methods(h, function_proto, [
// ... existing ...
#("map", ArrayNative(ArrayPrototypeMap), 1), // name, wrapped variant, .length
])
let #(h, static_methods) =
common.alloc_methods(h, function_proto, [
#("from", ArrayNative(ArrayFrom), 1),
])
common.init_type(h, object_proto, function_proto, proto_methods, ..., static_methods)
}
src/arc/vm/exec/call.gleam — Wire new module (new globals only)Skip if adding methods to an existing type. For a new global (e.g. Date), add a dispatch case to dispatch_native:
pub fn dispatch_native(native, args, this, state, ...) {
case native {
// ... existing ...
value.DateNative(n) -> builtins_date.dispatch(n, args, this, state)
}
}
Add the import at the top of call.gleam.
src/arc/vm/builtins.gleam — Register new global (new globals only)Add import, add field to Builtins type, call <module>.init() in builtins.init(), add to builtins.globals().
test/compiler_test.gleam — Add testspub fn array_from_basic_test() -> Nil {
assert_normal("Array.from([1,2,3]).join(',')", JsString("1,2,3"))
}
pub fn array_from_throws_test() -> Nil {
assert_thrown("Array.from(null)")
}
Helpers: assert_normal(src, expected), assert_normal_number(src, float), assert_thrown(src).
gleam check — fast type checkgleam test — all existing + new tests must passState, not bare Heap. Access heap via state.heap.State(..state, heap: new_heap)state.type_error(state, msg) / state.range_error(state, msg) — returns #(State, Error(err))common.make_type_error(heap, builtins, msg) returns #(Heap, JsValue)use <- state.guard_length(state, length, "Invalid array length") throws RangeError if length > limits.max_iterationCall a JS callback via state.call (DI function field on State):
use result, state <- state.try_call(state, callback, this_arg, [arg1, arg2])
Or lower-level: case state.call(state, fn_val, this, args) { Ok(#(v, state)) -> ..., Error(#(thrown, state)) -> ... }
use str, state <- state.try_to_string(state, val) // full ToPrimitive, re-enters VM
helpers.to_number_int(val) |> option.unwrap(0) // simple Number coercion
object.get_value_of(state, val, key) — top-level [[Get]] for any JsValue (handles primitive→prototype)object.get_value(state, ref, key, receiver) — [[Get]] on a Ref (proto walk + getter invocation)object.set_value(state, ref, key, val, receiver) — [[Set]] (setter invocation + non-writable check)heap.read(h, ref) / heap.write(h, ref, slot) — direct heap slot accesscommon.alloc_array(heap, list_of_values, array_proto) → #(Heap, Ref)heap.alloc(heap, ObjectSlot(kind: OrdinaryObject, properties: dict, elements: elements.new(), prototype: Some(proto), symbol_properties: dict.new(), extensible: True))common.alloc_native_fn(h, function_proto, variant, name, length)JsUndefined, JsNull, JsBool(Bool), JsNumber(JsNum), JsString(String), JsObject(Ref), JsBigInt(Int), JsSymbol(SymbolId)JsNum: Finite(Float) | NaN | Infinity | NegInfinity (BEAM can't represent NaN/Inf as native floats)value.data_property(v) (enumerable/writable/configurable true), value.builtin_property(v) (non-enumerable)