mirror of
https://github.com/vlang/v.git
synced 2025-09-11 08:25:42 -04:00
parent
3f76b69165
commit
27829d56cd
@ -329,6 +329,20 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeConfig) {
|
|||||||
g.writeln('function ${c.typ_name}__eq(self,other) { return ${c.eq}; } ')
|
g.writeln('function ${c.typ_name}__eq(self,other) { return ${c.eq}; } ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g JsGen) gen_nil_const() {
|
||||||
|
g.writeln('const nil__ = new \$ref(new nil());')
|
||||||
|
g.gen_builtin_prototype(
|
||||||
|
typ_name: 'nil'
|
||||||
|
val_name: 'str'
|
||||||
|
default_value: 'new String("&nil")'
|
||||||
|
constructor: 'this.str = str.toString(); this.len = this.str.length'
|
||||||
|
value_of: 'null'
|
||||||
|
to_string: '"&nil"'
|
||||||
|
eq: 'new bool(self.valueOf() === other.valueOf())'
|
||||||
|
to_jsval: 'null'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// generate builtin type definitions, used for casting and methods.
|
// generate builtin type definitions, used for casting and methods.
|
||||||
fn (mut g JsGen) gen_builtin_type_defs() {
|
fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
|
@ -143,6 +143,7 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) stri
|
|||||||
graph.add(g.file.mod.name, imports)
|
graph.add(g.file.mod.name, imports)
|
||||||
// builtin types
|
// builtin types
|
||||||
if g.file.mod.name == 'builtin' && !g.generated_builtin {
|
if g.file.mod.name == 'builtin' && !g.generated_builtin {
|
||||||
|
g.gen_nil_const()
|
||||||
g.gen_builtin_type_defs()
|
g.gen_builtin_type_defs()
|
||||||
g.writeln('Object.defineProperty(array.prototype,"len", { get: function() {return new int(this.arr.arr.length);}, set: function(l) { this.arr.arr.length = l.valueOf(); } }); ')
|
g.writeln('Object.defineProperty(array.prototype,"len", { get: function() {return new int(this.arr.arr.length);}, set: function(l) { this.arr.arr.length = l.valueOf(); } }); ')
|
||||||
g.writeln('Object.defineProperty(map.prototype,"len", { get: function() {return new int(this.length);}, set: function(l) { } }); ')
|
g.writeln('Object.defineProperty(map.prototype,"len", { get: function() {return new int(this.length);}, set: function(l) { } }); ')
|
||||||
@ -965,7 +966,7 @@ fn (mut g JsGen) expr(node_ ast.Expr) {
|
|||||||
g.gen_lock_expr(node)
|
g.gen_lock_expr(node)
|
||||||
}
|
}
|
||||||
ast.Nil {
|
ast.Nil {
|
||||||
g.write('null')
|
g.write('nil__')
|
||||||
}
|
}
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
ast.None {
|
ast.None {
|
||||||
@ -1345,7 +1346,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
|||||||
g.expr(left)
|
g.expr(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
is_ptr := stmt.op == .assign && stmt.left_types[i].is_ptr() && !array_set
|
is_ptr := stmt.op == .assign && stmt.right_types[i].is_ptr() && !array_set
|
||||||
if is_ptr {
|
if is_ptr {
|
||||||
g.write('.val')
|
g.write('.val')
|
||||||
}
|
}
|
||||||
|
74
vlib/v/gen/js/tests/unsafe.v
Normal file
74
vlib/v/gen/js/tests/unsafe.v
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
struct Bar {
|
||||||
|
value int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo1 {
|
||||||
|
mut:
|
||||||
|
name &string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo2 {
|
||||||
|
mut:
|
||||||
|
name ?&string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo3 {
|
||||||
|
mut:
|
||||||
|
bar &Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Basic test of assigning nil to a string pointer
|
||||||
|
mut str := 'hi!'
|
||||||
|
mut str_ptr := &str
|
||||||
|
unsafe {
|
||||||
|
str_ptr = nil
|
||||||
|
}
|
||||||
|
println(str_ptr) // should print '&nil'
|
||||||
|
assert str_ptr == unsafe { nil }
|
||||||
|
|
||||||
|
// Test initializing a pointer field with nil
|
||||||
|
f1 := Foo1{
|
||||||
|
name: unsafe { nil }
|
||||||
|
}
|
||||||
|
assert f1.name == unsafe { nil }
|
||||||
|
|
||||||
|
// Test assigning nil to an optional pointer field
|
||||||
|
mut f2 := Foo2{}
|
||||||
|
unsafe {
|
||||||
|
f2.name = nil
|
||||||
|
}
|
||||||
|
if f2.name != none {
|
||||||
|
assert f2.name == unsafe { nil }
|
||||||
|
} else {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test assigning nil to a struct pointer
|
||||||
|
mut f3 := &Foo2{}
|
||||||
|
unsafe {
|
||||||
|
f3 = nil
|
||||||
|
}
|
||||||
|
assert f3 == unsafe { nil }
|
||||||
|
|
||||||
|
// Test with custom struct fields
|
||||||
|
mut f4 := Foo3{
|
||||||
|
bar: &Bar{42}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
f4.bar = nil
|
||||||
|
}
|
||||||
|
assert f4.bar == unsafe { nil }
|
||||||
|
|
||||||
|
// Test with nil pointers in arrays
|
||||||
|
mut ptrs := []&string{len: 3, init: unsafe { nil }}
|
||||||
|
p0, p1 := 'hello', 'world'
|
||||||
|
ptrs[0] = &p0
|
||||||
|
ptrs[1] = &p1
|
||||||
|
unsafe {
|
||||||
|
ptrs[2] = nil
|
||||||
|
}
|
||||||
|
assert ptrs[0] != unsafe { nil }
|
||||||
|
assert ptrs[1] != unsafe { nil }
|
||||||
|
assert ptrs[2] == unsafe { nil }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user