@@ -362,58 +362,16 @@ function toJsType(field, parentIsInterface = false) {
362362 return type ;
363363}
364364
365- function syntaxForType ( type ) {
366-
367- var syntax = null ;
368- var namespace = type ;
369-
370- while ( syntax === null && namespace !== null ) {
371- if ( namespace . options != null && "syntax" in namespace . options ) {
372- syntax = namespace . options [ "syntax" ] ;
373- }
374- else {
375- namespace = namespace . parent ;
376- }
377- }
378-
379- return syntax !== null ? syntax : "proto2" ;
380- }
381-
382- function isExplicitPresence ( field , syntax ) {
383-
384- // In proto3, optional fields are explicit
385- if ( syntax === "proto3" ) {
386- return field . options != null && field . options [ "proto3_optional" ] === true ;
387- }
388-
389- // In proto2, fields are explicitly optional if they are not part of a map, array or oneOf group
390- if ( syntax === "proto2" ) {
391- return field . optional && ! ( field . partOf || field . repeated || field . map ) ;
392- }
393-
394- throw new Error ( "Unknown proto syntax: [" + syntax + "]" ) ;
395- }
396-
397- function isImplicitPresence ( field , syntax ) {
398-
399- // In proto3, everything not marked optional has implicit presence (including maps and repeated fields)
400- if ( syntax === "proto3" ) {
401- return field . options == null || field . options [ "proto3_optional" ] !== true ;
402- }
403-
404- // In proto2, nothing has implicit presence
405- if ( syntax === "proto2" ) {
365+ function hasPresence ( field ) {
366+ if ( field . repeated || field . map ) {
406367 return false ;
407368 }
408-
409- throw new Error ( "Unknown proto syntax: [" + syntax + "]" ) ;
369+ return field . partOf || // oneofs
370+ field . declaringField || field . extensionField || // extensions
371+ field . _features . field_presence === "EXPLICIT" ;
410372}
411373
412- function isOptionalOneOf ( oneof , syntax ) {
413-
414- if ( syntax === "proto2" ) {
415- return false ;
416- }
374+ function isProto3Optional ( oneof ) {
417375
418376 if ( oneof . fieldsArray == null || oneof . fieldsArray . length !== 1 ) {
419377 return false ;
@@ -426,8 +384,6 @@ function isOptionalOneOf(oneof, syntax) {
426384
427385function buildType ( ref , type ) {
428386
429- var syntax = syntaxForType ( type ) ;
430-
431387 if ( config . comments ) {
432388 var typeDef = [
433389 "Properties of " + aOrAn ( type . name ) + "." ,
@@ -443,13 +399,15 @@ function buildType(ref, type) {
443399 // With semantic nulls, only explicit optional fields and one-of members can be set to null
444400 // Implicit fields (proto3), maps and lists can be omitted, but if specified must be non-null
445401 // Implicit fields will take their default value when the message is constructed
446- if ( isExplicitPresence ( field , syntax ) || field . partOf ) {
447- jsType = jsType + "|null|undefined" ;
448- nullable = true ;
449- }
450- else if ( isImplicitPresence ( field , syntax ) || field . repeated || field . map ) {
451- jsType = jsType + "|undefined" ;
452- nullable = true ;
402+ if ( field . optional ) {
403+ if ( hasPresence ( field ) ) {
404+ jsType = jsType + "|null|undefined" ;
405+ nullable = true ;
406+ }
407+ else {
408+ jsType = jsType + "|undefined" ;
409+ nullable = true ;
410+ }
453411 }
454412 }
455413 else {
@@ -490,7 +448,7 @@ function buildType(ref, type) {
490448 // With semantic nulls, fields are nullable if they are explicitly optional or part of a one-of
491449 // Maps, repeated values and fields with implicit defaults are never null after construction
492450 // Members are never undefined, at a minimum they are initialized to null
493- if ( isExplicitPresence ( field , syntax ) || field . partOf ) {
451+ if ( hasPresence ( field ) && field . optional ) {
494452 jsType = jsType + "|null" ;
495453 }
496454 }
@@ -514,7 +472,7 @@ function buildType(ref, type) {
514472 // With semantic nulls, only explict optional fields and one-of members are null by default
515473 // Otherwise use field.optional, which doesn't consider proto3, maps, repeated fields etc.
516474 var nullDefault = config [ "null-semantics" ]
517- ? isExplicitPresence ( field , syntax )
475+ ? hasPresence ( field ) && field . optional
518476 : field . optional && config [ "null-defaults" ] ;
519477 if ( field . repeated )
520478 push ( escapeName ( type . name ) + ".prototype" + prop + " = $util.emptyArray;" ) ; // overwritten in constructor
@@ -546,7 +504,7 @@ function buildType(ref, type) {
546504 }
547505 oneof . resolve ( ) ;
548506 push ( "" ) ;
549- if ( isOptionalOneOf ( oneof , syntax ) ) {
507+ if ( isProto3Optional ( oneof ) ) {
550508 push ( "// Virtual OneOf for proto3 optional field" ) ;
551509 }
552510 else {
0 commit comments