원클릭으로
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)