Reading `SomeClass.null` permanently breaks that class's static `valueOf()`
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 55/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- android, cpp, javascript
- Área
- mobile-dev
Línea de trabajo
Comienza con test-app/runtime/src/main/cpp/MetadataNode.cpp, leyendo NullObjectAccessorGetterCallback y NullValueOfCallback; después, ejecuta la reproducción del inspector con java.lang.Double o java.lang.String. Se considera terminado cuando leer el marcador .null de una clase ya no cambia su comportamiento estático de valueOf, mientras que la resolución de argumentos typed-null sigue reconociendo el marcador.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
Reading the typed-null marker SomeJavaClass.null permanently breaks SomeJavaClass.valueOf(...) for the remaining life of the isolate — it silently starts returning null for every argument.
The .null getter deletes the class's Java static valueOf and replaces it with an internal shim that unconditionally returns null. Because the marker object is the constructor function itself, that shim lands directly on the class.
This is not specific to any one class; it hits any class that has both a static valueOf and gets a typed null taken from it. In practice java.lang.String.valueOf(...) is broken from app startup in most apps, because passing java.lang.String.null is the idiomatic way to disambiguate a null argument.
Reproduction
Any app, evaluated in the runtime (here via the inspector):
String(java.lang.Double.valueOf(1)) // "1.0" <- correct
typeof java.lang.Double.null // "function" <- touch the marker once
String(java.lang.Double.valueOf(1)) // "null" <- now permanently broken
java.lang.Double.toString(1) // "1.0" <- other statics unaffected
The property is visibly deleted and re-added — valueOf moves from its metadata slot to the end of the key order:
Object.getOwnPropertyNames(java.lang.Double).indexOf("valueOf") // 19 (of 35) before
Object.getOwnPropertyNames(java.lang.Double).indexOf("valueOf") // 34 (of 35) after
java.lang.String shows the post-mutation shape from startup in any app that uses java.lang.String.null:
String(java.lang.String.valueOf(7)) // "null"
Object.getOwnPropertyNames(java.lang.String)
// [... "copyValueOf", "format", "join", "extend", "CASE_INSENSITIVE_ORDER", "null", "class", "valueOf"]
// ^ moved to last
Expected vs actual
- Expected:
java.lang.String.valueOf(42)→"42"; takingSomeClass.nullhas no effect on that class's static methods. - Actual: returns
null, silently, forever after the first read of.nullon that class.
Root cause
test-app/runtime/src/main/cpp/MetadataNode.cpp, NullObjectAccessorGetterCallback (the getter installed for .null):
auto thiz = info.This(); // the class constructor function itself
...
auto funcTemplate = FunctionTemplate::New(isolate, MetadataNode::NullValueOfCallback);
thiz->Delete(context, V8StringConstants::GetValueOf(isolate));
thiz->Set(context, V8StringConstants::GetValueOf(isolate),
funcTemplate->GetFunction(context).ToLocalChecked());
...
info.GetReturnValue().Set(thiz); // the marker IS the ctor function
and NullValueOfCallback is simply:
args.GetReturnValue().SetNull();
So the "make this object read as null" shim is installed on the class object rather than on a distinct marker object, and it overwrites a real Java static of the same name. The guard around it (hiddenVal.IsEmpty()) only makes it happen once — it does not make it reversible.
Suggested direction
Return a dedicated marker object from the .null getter instead of the constructor function itself — e.g. an empty object carrying the same MetadataNodeKeys internal fields plus the null-node private value, with valueOf installed on that. The argument-resolution path already identifies typed nulls via the NULL_NODE_NAME private value, so it should not need the marker to be the class object.
Failing that, at minimum the shim should not clobber a name that exists in the class's metadata.
Affected versions
- Reproduced on
@nativescript/android9.0.x (V8 10.3.22), the currently published runtime. - Also reproduces unchanged on a local branch running V8 14.9.207.39, so it is independent of the V8 version — this is long-standing, not a recent regression.
Tested on an API 35 arm64 emulator.
- Lenguaje dominante
- C++
- Estrellas
- 563
- Forks
- 144
- Merge medio
- 10 h 46 min
- PR fusionados (30 d)
- 14
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de NativeScript/android
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 38/100
NativeScript/android#2039 · 1 comentario ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
NativeScript/android#2024 ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
NativeScript/android#2020 ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 42/100
NativeScript/android#2019 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 52/100
NativeScript/android#1982 ·
Todos los issues de NativeScript/android
Issues similares
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 92/100
autowarefoundation/autoware_universe#13413 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
-
automated-analysis bug memory-safety
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
-
Sensor initialization takes very long when `--initial-sim-time` is set to current UNIX timestamp Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
gazebosim/gz-sensors#662 · 1 comentario ·